]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
search: Highlight search terms in description
authorRares Visalom <rares.visalom@gmail.com>
Tue, 27 Jun 2017 22:01:13 +0000 (01:01 +0300)
committerFlorian Müllner <fmuellner@gnome.org>
Fri, 14 Jul 2017 20:40:25 +0000 (22:40 +0200)
The classes extending the SearchResult can now connect
to the 'terms-changed' signal emitted by the SearchResult
class. This signal enables each object to update its
internal description in order to apply the bold style
onto strings that match the search terms.

https://bugzilla.gnome.org/show_bug.cgi?id=749957

js/ui/search.js

index 3da5fde6cd33ab4d532ef566fbc08e7e852b3d1a..dd3ea1318a13ce666a5ff43042349a133f9260a6 100644 (file)
@@ -84,6 +84,8 @@ const ListSearchResult = new Lang.Class({
                                          vertical: false });
         this.actor.set_child(content);
 
+        this._termsChangedId = 0;
+
         let titleBox = new St.BoxLayout({ style_class: 'list-search-result-title' });
 
         content.add(titleBox, { x_fill: true,
@@ -106,14 +108,31 @@ const ListSearchResult = new Lang.Class({
         this.actor.label_actor = title;
 
         if (this.metaInfo['description']) {
-            let description = new St.Label({ style_class: 'list-search-result-description',
-                                             text: this.metaInfo['description'] });
+            this._descriptionLabel = new St.Label({ style_class: 'list-search-result-description' });
+            content.add(this._descriptionLabel, { x_fill: false,
+                                                  y_fill: false,
+                                                  x_align: St.Align.START,
+                                                  y_align: St.Align.MIDDLE });
 
-            content.add(description, { x_fill: false,
-                                       y_fill: false,
-                                       x_align: St.Align.START,
-                                       y_align: St.Align.MIDDLE });
+            this._termsChangedId =
+                this._resultsView.connect('terms-changed',
+                                          Lang.bind(this, this._highlightTerms));
+
+            this._highlightTerms();
         }
+
+        this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
+    },
+
+    _highlightTerms: function() {
+        let markup = this._resultsView.highlightTerms(this.metaInfo['description']);
+        this._descriptionLabel.clutter_text.set_markup(markup);
+    },
+
+    _onDestroy: function() {
+        if (this._termsChangedId)
+            this._resultsView.disconnect(this._termsChangedId);
+        this._termsChangedId = 0;
     }
 });
 
@@ -234,7 +253,6 @@ const SearchResultsBase = new Lang.Class({
 
     updateSearch: function(providerResults, terms, callback) {
         this._terms = terms;
-
         if (providerResults.length == 0) {
             this._clearResultDisplay();
             this.actor.hide();
@@ -423,6 +441,8 @@ const SearchResults = new Lang.Class({
 
         this._providers = [];
 
+        this._highlightRegex = null;
+
         this._searchSettings = new Gio.Settings({ schema_id: SEARCH_PROVIDERS_SCHEMA });
         this._searchSettings.connect('changed::disabled', Lang.bind(this, this._reloadRemoteProviders));
         this._searchSettings.connect('changed::enabled', Lang.bind(this, this._reloadRemoteProviders));
@@ -542,6 +562,11 @@ const SearchResults = new Lang.Class({
 
         if (this._searchTimeoutId == 0)
             this._searchTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 150, Lang.bind(this, this._onSearchTimeout));
+
+        let escapedTerms = this._terms.map(term => Shell.util_regex_escape(term));
+        this._highlightRegex = new RegExp(`(${escapedTerms.join('|')})`, 'gi');
+
+        this.emit('terms-changed');
     },
 
     _onPan: function(action) {
@@ -680,8 +705,19 @@ const SearchResults = new Lang.Class({
         } else {
             result.actor.remove_style_pseudo_class('selected');
         }
+    },
+
+    highlightTerms: function(description) {
+        if (!description)
+            return '';
+
+        if (!this._highlightRegex)
+            return description;
+
+        return description.replace(this._highlightRegex, '<b>$1</b>');
     }
 });
+Signals.addSignalMethods(SearchResults.prototype);
 
 const ProviderInfo = new Lang.Class({
     Name: 'ProviderInfo',